<?php
/**
 * Created by PhpStorm.
 * User: Jerry
 * Date: 3/17/2020
 * Time: 8:18 PM
 * Note: verify.php
 */

namespace app\lib;

use Ext\libLog;

class verify extends base
{
    const APP_KEY = '%C}!H]Z*@R|UUZxc6l@G[cI@';
    const WEB_KEY = '@R|UUZH]Z*@R|UHYSgtG7LO4';
    public string $ss = '';

    public function check(int $check_type): void
    {
        $data_pack = $this->io_unit->src_input;

        //libLog::new('api_data')->add($data_pack)->save();

        //检查签名参数
        if (!isset($data_pack['u'])
            || !isset($data_pack['t'])
            || !isset($data_pack['s'])) {
            $this->fail(10011);
        }

        //检查时间戳合法性
        $data_pack['t'] = (string)((int)$data_pack['t']);

        if (strlen($data_pack['t']) < 10) {
            $this->fail(10011);
        }

        //提取签名
        $data_sign = &$data_pack['s'];
        unset($data_pack['s']);

        //获取时间戳末位整形
        $skip_id = (int)substr($data_pack['t'], -1, 1);

        //重组key
        $key_const = $check_type ? self::WEB_KEY : self::APP_KEY;
        $key_arr   = str_split($key_const);
        unset($key_arr[$skip_id]);
        $app_key = implode($key_arr);

        //并入数据包
        $data_pack['k'] = &$app_key;

        $this->ss = $data_pack['ss'] ?? '';
        unset($data_pack['ss']);

        //按key升序排列
        ksort($data_pack);

        //开始合并非数组类参数
        $data_string = '';

        foreach ($data_pack as $value) {
            if (is_array($value) || is_object($value)) {
                continue;
            }

            $data_string .= (string)$value;
        }

        //计算md5签名
        $data_hash = hash('md5', $data_string);

        //对比签名
        if ($data_sign !== $data_hash) {
            //记录日志
            libLog::new('data_verify')
                ->add([
                    'ip'          => $this->app->client_ip,
                    'cmd'         => $this->io_unit->src_cmd,
                    'client_sign' => &$data_sign,
                    'server_sign' => &$data_hash,
                    'sign_data'   => &$data_pack,
                    'input_data'  => $this->io_unit->src_input,
                    'data_string' => $data_string,
                    'ss'          => $this->ss
                ])
                ->save();

            //退出
            $this->fail(10012);
        }
    }
}